home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Hot Mix 17
/
Hot Mix 17.iso
/
HM17_SGI
/
research
/
examples
/
insight
/
plugins
/
mylinsys.pro
< prev
next >
Wrap
Text File
|
1997-07-08
|
19KB
|
553 lines
; $Id: mylinsys.pro,v 1.13 1997/04/22 17:12:33 rob Exp $
;
; Copyright (c) 1997, Research Systems, Inc. All rights reserved.
; Unauthorized reproduction prohibited.
;+
; FILE:
; mylinsys.pro
;
; PURPOSE:
; This file contains an Analysis PlugIn that computes the
; solution of an N-by-N linear system of equations using
; one of three methods.
;
; CONTENTS:
; GENERAL ROUTINES
; pro HandleEventsMylinsys - handle dialog box events
;
; CALLBACK ROUTINES
; fun ApplyMyLinSys - Apply/OK entry point
; fun PromptUserMyLinSys - main entry point (creates dialog)
;
; REGISTRATION FUNCTION
; fun MyLinSys - registers the PlugIn
;
;-
FORWARD_FUNCTION NORM
; *****************************************************************************
; GENERAL ROUTINES
; *****************************************************************************
; -----------------------------------------------------------------------------
;
; Purpose: Handle dialog events.
;
pro HandleEventsMyLinSys, sEvent
; Widget state information.
;
common MyLinSysCommon, psState
wGroup = (*psState).wMainBase
; Catch errors.
;
CATCH, error
if (error ne 0) then begin
CATCH, /CANCEL
void = DIALOG_MESSAGE(!ERR_STRING, DIALOG_PARENT=wGroup)
RETURN
endif
; ========================
; PROCESS EVENTS
; ========================
case (sEvent.id) of
; --------------------------------------
; Array Input text
; --------------------------------------
(*psState).wArrayInputText: begin
; (nothing to do now)
end
; --------------------------------------
; Vector Input text
; --------------------------------------
(*psState).wVectorInputText: begin
; (nothing to do now)
end
; --------------------------------------
; Input browse button for 2D array
; --------------------------------------
(*psState).wArrayInputBrowseButton: begin
; Let user browser for an array data name.
;
void = INSGET( $
NAME=inputArrayName, $ ; returned name of data selected
/EXCLUSIVE, $ ; only one selection
TITLE='Select an array.', $ ; title of browser
DIMS_LIST=2, $ ; show 2D array data only
COUNT=count, $ ; returned count of items selected
GROUP=wGroup, $ ; widget group leader
_EXTRA=(*psState).extra) ; extra information
; If user selected an item, set data name in text widget.
;
if (count eq 1) then $
WIDGET_CONTROL, (*psState).wArrayInputText, $
SET_VALUE=inputArrayName
end
; --------------------------------------
; Input browse button for 1D vector
; --------------------------------------
(*psState).wVectorInputBrowseButton: begin
; Let user browser for a vector data name.
;
void = INSGET( $
NAME=inputVectorName, $ ; returned name of data selected
/EXCLUSIVE, $ ; only one selection
TITLE='Select a vector.', $ ; title of browser
DIMS_LIST=1, $ ; show 1D array data only
COUNT=count, $ ; returned count of items selected
GROUP=wGroup, $ ; widget group leader
_EXTRA=(*psState).extra) ; extra information
; If user selected an item, set data name in text widget.
;
if (count eq 1) then $
WIDGET_CONTROL, (*psState).wVectorInputText, $
SET_VALUE=inputVectorName
end
; --------------------------------------
; Method bgroup
; --------------------------------------
(*psState).wLinSysBgroup: begin
WIDGET_CONTROL, (*psState).wLinSysBgroup, GET_VALUE=value
(*psState).LinSysMethod = value
end
; --------------------------------------
; Double bgroup
; --------------------------------------
(*psState).wDoubleBgroup: begin
WIDGET_CONTROL, (*psState).wDoubleBgroup, GET_VALUE=value
(*psState).DoubleMethod = value
end
; --------------------------------------
; Summary bgroup
; --------------------------------------
(*psState).wSummaryBgroup: begin
WIDGET_CONTROL, (*psState).wSummaryBgroup, GET_VALUE=value
(*psState).SummaryMethod = value
end
; --------------------------------------
; OK/Apply/Cancel buttons
; --------------------------------------
(*psState).wOKApplyCancelButtons: begin
; Destroy dialog on successful OK selection, or if user canceled.
;
if ((sEvent.type eq 'OK') or $
(sEvent.type eq 'Cancel')) then $
WIDGET_CONTROL, (*psState).wMainBase, /DESTROY
end
; --------------------------------------
; other events
; --------------------------------------
else: ; (do nothing)
endcase
end ; HandleEventsMyLinSys
; *****************************************************************************
; CALLBACK ROUTINES
; *****************************************************************************
; -----------------------------------------------------------------------------
;
; Purpose: Get data and solve linear system.
; Fuction returns 1B on success, else 0B.
;
function ApplyMyLinSys, $
CIDs=CIDs, $ ; OUT: command ID list from INSPUT/INSVIS calls
_EXTRA=extra ; IN: information to pass to commands
; Widget state information.
;
common MyLinSysCommon, psState
wGroup = (*psState).wMainBase
; ---------------------------------------------------------
; Catch errors.
; ---------------------------------------------------------
CATCH, error
if (error ne 0) then begin
CATCH, /CANCEL
void = DIALOG_MESSAGE(!ERR_STRING, DIALOG_PARENT=wGroup)
RETURN, 0B
endif
; ---------------------------------------------------------
; Check inputs.
; ---------------------------------------------------------
; Get and check array input data name.
;
WIDGET_CONTROL, (*psState).wArrayInputText, GET_VALUE=inputArrayName
inputArrayName = inputArrayName[0]
if (inputArrayName eq '') then $
MESSAGE, 'Must specify Array Input data.', /NONAME
; Get array input data.
;
inputArrayData = INSGET( $
inputArrayName, $ ; name of array data to get
COUNT=count, $ ; returned number of items found
DIMS_LIST=2, $ ; data should have this dimensionality
GROUP=wGroup, $ ; widget group leader
_EXTRA=extra) ; extra information
; Return if data not found (INSGET displays own error messages).
;
if (count ne 1) then $
RETURN, 0B
; Get and check vector input data name.
;
WIDGET_CONTROL, (*psState).wVectorInputText, GET_VALUE=inputVectorName
inputVectorName = inputVectorName[0]
if (inputVectorName eq '') then $
MESSAGE, 'Must specify Vector Input data.', /NONAME
; Get vector input data.
;
inputVectorData = INSGET( $
inputVectorName, $ ; name of vector data to get
COUNT=count, $ ; returned number of items found
DIMS_LIST=1, $ ; data should have this dimensionality
GROUP=wGroup, $ ; widget group leader
_EXTRA=extra) ; extra information
; Return if data not found (INSGET displays own error messages).
;
if (count ne 1) then $
RETURN, 0B
; Check input data for correct size.
; The array must be square.
; The array column dimension must match the vector length.
;
aDim = SIZE(inputArrayData)
vDim = SIZE(inputVectorData)
if (aDim[1] ne aDim[2]) then $
MESSAGE, 'Array Input must be square.', /NONAME
if (aDim[2] ne vDim[vDim[0]+2]) then $
MESSAGE, 'Array Input and Vector Input are of incompatible size. ' $
+ 'Select a Vector Input with a length of ' $
+ STRCOMPRESS(STRING(aDim[2]), /REMOVE_ALL) + '.', /NONAME
; ---------------------------------------------------------
; Compute the solution using one of three methods.
; ---------------------------------------------------------
; Put up wait cursor.
;
WIDGET_CONTROL, (*psState).wMainBase, /HOURGLASS
start = SYSTIME(1)
; Use Biconjugate Gradient.
;
if ((*psState).LinSysMethod eq 0) then begin
newData = LINBCG(SPRSIN(inputArrayData, $
DOUBLE=(*psState).DoubleMethod), inputVectorData, $
REPLICATE(MEDIAN(inputVectorData, /EVEN), $
N_ELEMENTS(inputVectorData)), $
ITOL=1, DOUBLE=(*psState).DoubleMethod)
; Use LU decomposition.
;
endif else if ((*psState).LinSysMethod eq 1) then begin
LUDC, inputArrayData, index, DOUBLE=(*psState).DoubleMethod
newData = LUSOL(inputArrayData, index, inputVectorData, $
DOUBLE=(*psState).DoubleMethod)
; Get "fresh" copy of Array Input data.
;
inputArrayData = INSGET( $
inputArrayName, $
COUNT=count, $
DIMS_LIST=2, $
GROUP=wGroup, $
_EXTRA=extra)
; Use SV decomposition.
;
endif else begin
SVDC, inputArrayData, w, u, v, DOUBLE=(*psState).DoubleMethod
newData = SVSOL(u, w, v, inputVectorData, $
DOUBLE=(*psState).DoubleMethod)
endelse
stop = SYSTIME(1)
; ---------------------------------------------------------
; Put the solution into the Insight Data Manager.
; ---------------------------------------------------------
description = 'LinSys ' + inputVectorName
outputName = (*psState).outputName
INSPUT, $
newData, $ ; the data
DESCRIPTION=description, $ ; data description
NAME=outputName, $ ; use this data name
COUNT=count, $ ; returned # of items put
CIDs=CIDs, $ ; command ID list
GROUP=wGroup, $ ; widget group leader
_EXTRA=extra ; extra information
; Return if "put" failed.
;
if (count ne 1) then $
RETURN, 0B
; ---------------------------------------------------------
; Put the residual into Insight (Data Manager).
; ---------------------------------------------------------
description = 'Residual ' + inputVectorName
resName = 'LinSys Residual'
resData = TRANSPOSE(inputArrayData ## newData - inputVectorData)
INSPUT, $
resData, $ ; the data
DESCRIPTION=description, $ ; data description
NAME=resName, $ ; try this data name
NEW_NAME=resNameUsed, $ ; the data name actually used
REPLACE=2, $ ; prompt user if name conflict
COUNT=count, $ ; returned # of items put
CIDs=CIDs, $ ; command ID list
GROUP=wGroup, $ ; widget group leader
_EXTRA=extra ; extra information
; Return if "put" failed.
;
if (count ne 1) then $
RETURN, 0B
; ---------------------------------------------------------
; Visualize the residual (error plot).
; ---------------------------------------------------------
INSVIS, $
resNameUsed, $ ; name of data item
TYPE='plot', $ ; visualization type
MODE='new', $ ; insert | new | overlay
CIDs=CIDs, $ ; command ID list
GROUP=wGroup, $ ; widget group leader
_EXTRA=extra ; extra information
; ---------------------------------------------------------
; Create a summary box.
; ---------------------------------------------------------
if ((*psState).SummaryMethod eq 1) then begin
msg1 = 'Residual Norm: |Ax - b| =' + $
STRING(NORM(resData, DOUBLE=(*psState).DoubleMethod))
msg2 = 'Method Timing:' + STRING(FLOAT(stop-start)) + ' Seconds'
void = DIALOG_MESSAGE([[msg1], [msg2]], /INFORMATION, $
TITLE='Linear Systems Summary', $
DIALOG_PARENT=(*psState).wMainBase)
endif
; ---------------------------------------------------------
; Successful return.
; ---------------------------------------------------------
RETURN, 1B
end ; ApplyMyLinSys
; -----------------------------------------------------------------------------
;
; Purpose: Main entry point for the PlugIn.
;
pro PromptUserMyLinSys, $
GROUP=wGroup, $ ; IN: group leader widget ID
_EXTRA=extra ; IN: various information
; Widget state information.
;
common MyLinSysCommon, psState
; Create modal main base (non-sizable).
;
title = 'Analysis PlugIn - Linear System of Equations'
wMainBase = WIDGET_BASE(TITLE=title, GROUP_LEADER=wGroup, $
/COLUMN, /MODAL, /TLB_FRAME_ATTR)
value = [ $
'Select a 2D array (A) and a 1D vector (b) that define a', $
'Linear System of Equations, Ax = b.', $
'The solution (x) is available through the Data Manager.', $
'The residual (Ax - b) is displayed as an XY plot.' $
]
for i = 0, N_ELEMENTS(value)-1 do $
void = WIDGET_LABEL(wMainBase, VALUE=value[i])
; ------------------------------------------
; Create INPUTS widgets.
; ------------------------------------------
wInputsBase = WIDGET_BASE(wMainBase, /COLUMN, /FRAME)
void = WIDGET_LABEL(wInputsBase, VALUE='INPUTS')
; Array Input.
;
wInputDataBase = WIDGET_BASE(wInputsBase, /ROW)
void = WIDGET_LABEL(wInputDataBase, VALUE='Array Input: ')
wArrayInputText = WIDGET_TEXT(wInputDataBase, VALUE='', /EDITABLE)
wArrayInputBrowseButton = $
WIDGET_BUTTON(wInputDataBase, VALUE=' Browse... ')
; Vector Input.
;
wInputDataBase = WIDGET_BASE(wInputsBase, /ROW)
void = WIDGET_LABEL(wInputDataBase, VALUE='Vector Input: ')
wVectorInputText = WIDGET_TEXT(wInputDataBase, VALUE='', /EDITABLE)
wVectorInputBrowseButton = $
WIDGET_BUTTON(wInputDataBase, VALUE=' Browse... ')
wLinSysBase = WIDGET_BASE(wInputsBase, /ROW)
void = WIDGET_LABEL(wLinSysBase, VALUE='Method: ')
wLinSysBgroup = CW_BGROUP(wLinSysBase, $
['Biconjugate Gradient', 'LU Decomposition', 'SV Decomposition'], $
/NO_RELEASE, /ROW, /RETURN_NAME, /EXCLUSIVE, SET_VALUE=1)
LinSysMethod = 1 ; (set default method to LU Decomposition)
wBottomBase = WIDGET_BASE(wMainBase, /ROW)
; ------------------------------------------
; Create OPTIONS widgets.
; ------------------------------------------
wOptionsLabelBase = WIDGET_BASE(wBottomBase, /COLUMN, /FRAME)
void = WIDGET_LABEL(wOptionsLabelBase, VALUE='OPTIONS')
wOptionsBase = WIDGET_BASE(wOptionsLabelBase, /ROW)
wDoubleBgroup = CW_BGROUP(wOptionsBase, 'Double Precision', $
/NONEXCLUSIVE, SET_VALUE=0)
DoubleMethod = 0
wSummaryBgroup = CW_BGROUP(wOptionsBase, 'Summary', $
/NONEXCLUSIVE, SET_VALUE=1)
SummaryMethod = 1
; ------------------------------------------
; Create OUTPUTS widgets.
; ------------------------------------------
outputName = 'LinSys Solution'
wOutputsLabelBase = WIDGET_BASE(wBottomBase, /COLUMN, /FRAME)
void = WIDGET_LABEL(wOutputsLabelBase, VALUE='OUTPUTS')
wOutputsBase = WIDGET_BASE(wOutputsLabelBase, /ROW)
void = WIDGET_LABEL(wOutputsBase, $
VALUE=' Vector Output: '+outputName)
; ------------------------------------------
; Create OK/Apply/Cancel buttons using special compound widget.
; (Must pass in main modal base, used to set default and cancel buttons.)
;
wOKApplyCancelButtons = CW_INSAPPLY(wMainBase, _EXTRA=extra)
; Create dialog state information.
;
sState = { $
extra: extra, $
wMainBase: wMainBase, $
outputName: outputName, $
wArrayInputText: wArrayInputText, $
wArrayInputBrowseButton: wArrayInputBrowseButton, $
wVectorInputText: wVectorInputText, $
wVectorInputBrowseButton: wVectorInputBrowseButton, $
wLinSysBgroup: wLinSysBgroup, $
LinSysMethod: LinSysMethod, $
wOKApplyCancelButtons: wOKApplyCancelButtons, $
wDoubleBgroup: wDoubleBgroup, $
DoubleMethod: DoubleMethod, $
wSummaryBgroup: wSummaryBgroup, $
SummaryMethod:SummaryMethod $
}
; Store the state in a heap variable.
;
psState = PTR_NEW(sState, /NO_COPY)
; Realize the dialog box.
;
WIDGET_CONTROL, wMainBase, /REALIZE
; Start event loop.
;
XMANAGER, 'PromptUserMyLinSys', wMainBase, $
EVENT_HANDLER='HandleEventsMyLinSys'
; Remove widget state info.
;
PTR_FREE, psState
end ; PromptUserMyLinSys
; *****************************************************************************
; REGISTRATION FUNCTION
; *****************************************************************************
; -----------------------------------------------------------------------------
;
; Purpose: Register the Analysis PlugIn.
;
function MyLinSys
; Return the Analysis PlugIn Registration Structure.
;
RETURN, { $
type: 'Analysis_PlugIn', $ ; PlugIn type
title: 'My LinSys...', $ ; PlugIn type
purpose: 'Solve linear systems.', $ ; PlugIn purpose
main_proc: 'PromptUserMyLinSys', $ ; main callback
apply_func: 'ApplyMyLinSys', $ ; apply callback
version: '5.0', $ ; IDL version
revision: '1.0' $ ; PlugIn version
}
end ; MyLinSys
; -----------------------------------------------------------------------------